package com.legendshop.code.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.legendshop.code.db.Column;
import com.legendshop.code.db.DbSchemaProvider;
import com.legendshop.code.util.ClientException;
import com.legendshop.code.util.Log;
import com.legendshop.code.util.StringConverter;
import com.legendshop.code.util.StringUtil;
import com.legendshop.code.util.TimerUtil;

/**
 * 读取db-config.properties
 * 
 * 
 */
public class Config {
	private static Config _instance = null;
	private String author;
	private String version;
	private String dbType;
	private String dbSchema;
	private String dbUsername;
	private String dbPasswd;
	private String dbConnectString;
	private String dbDriver;
	private String packagePath;
	private String daoPackagePath;
	private String servicePackagePath;
	private String modelPackagePath;
	private String controllerPackagePath;
	private String serviceConstsPackagePath;
	private String xmlConfigPath;
	private String jspPath;
	private String path;
	private int logLevel;
	private String sequence;
	private String overWrite;
	private String tableList[];
	private Map<String,String> entityName;
	private int dataBaseType;
	private String actionPrex;
	private final Map<String, Map<String, Object>> contextMap = new HashMap<String, Map<String, Object>>();

	// 实体类和数据库表的对应字符串
	private String entityNameStr;
	private String tableListStr;

	private Config() {
		tableList = new String[0];
		entityName = new HashMap<String,String>();
		dataBaseType = 0;
		loadFromFile("db-config.properties");
		tableList = StringUtil.stringtoArray(tableListStr);
		entityName = getEntityName(tableList);
	}

	public Config(String file) {
		tableList = new String[0];
		entityName = new HashMap<String,String>();
		dataBaseType = 0;
		loadFromFile(file);
		tableList = StringUtil.stringtoArray(tableListStr);
		entityName = getEntityName(tableList);
	}

	public Map<String,String> getEntityName(String[] tableList) {
		Map<String,String> entityNames = new HashMap<String,String>();
		String entityList[] = StringUtil.stringtoArray(entityNameStr);
		if (tableList.length != entityList.length) {
			throw new ClientException("数据库表名和实体类名字长度不一致！", "error");
		}
		for (int i = 0; i < tableList.length; i++) {
			entityNames.put(tableList[i], entityList[i]);
		}
		return entityNames;
	}

	public static Config getInstance() {
		if (_instance == null) {
			_instance = new Config();
		}
		return _instance;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}

	public String getDbType() {
		return dbType;
	}

	public void setDbType(String dbType) {
		this.dbType = dbType;
	}

	public String getDbSchema() {
		return dbSchema;
	}

	public void setDbSchema(String dbSchema) {
		this.dbSchema = dbSchema;
	}

	public String getDbConnectString() {
		return dbConnectString;
	}

	public String getDbPasswd() {
		return dbPasswd;
	}

	public String getDbUsername() {
		return dbUsername;
	}

	public void setDbUsername(String dbUsername) {
		this.dbUsername = dbUsername;
	}

	public void setDbPasswd(String dbPasswd) {
		this.dbPasswd = dbPasswd;
	}

	public void setDbConnectString(String dbConnectString) {
		this.dbConnectString = dbConnectString;
	}

	public String getPackagePath() {
		return packagePath;
	}

	public void setPackagePath(String packagePath) {
		this.packagePath = packagePath;
	}

	public int getLogLevel() {
		return logLevel;
	}

	public void setLogLevel(int logLevel) {
		this.logLevel = logLevel;
	}

	public void setPath(String path) {
		if ((path == null) || (path.indexOf(File.separator) != path.length())) {
			path = path + File.separator;
		}
		this.path = path;
		Log.createDictory(getInstance().getPath() + File.separator + "log");
	}

	public String getPath() {
		return path;
	}

	public String getSequence() {
		return sequence;
	}

	public void setSequence(String sequence) {
		this.sequence = sequence;
	}

	public String[] getTableList() {
		return tableList;
	}

	public void setTableList(String tableList[]) {
		this.tableList = tableList;
	}

	public int getDataBaseType() {
		return dataBaseType;
	}

	public void setDataBaseType(int dataBaseType) {
		this.dataBaseType = dataBaseType;
	}

	public void loadFromFile(String file) {
		InputStream is = null;// 定义输入流is
		try {
			try {
				is = new FileInputStream(file);// 创建输入流
			} catch (Exception e) {
				if (file.startsWith("/"))
					// 用getResourceAsStream()方法用于定位并打开外部文件。
					is = Config.class.getResourceAsStream(file);
				else
					is = Config.class.getClassLoader().getResourceAsStream(file);
			}
			
			Properties p = new Properties();
			p.load(is);
			loadConfigFromProperties(p);
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(is != null){
				try {
					is.close();// 关闭输入流
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void writeToFile(String file) {
		try {
			Properties p = new Properties();
			setConfigToProperties(p);
			p.save(new FileOutputStream(new File(file)), "autoCode config");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void loadConfigFromProperties(Properties p) {
		author = p.getProperty("author");
		version = p.getProperty("version");
		dbType = p.getProperty("dbType");
		dbSchema = p.getProperty("dbSchema");
		dbUsername = p.getProperty("dbUsername");
		dbPasswd = p.getProperty("dbPasswd");
		dbConnectString = p.getProperty("dbConnectString");
		packagePath = p.getProperty("packagePath");
		path = p.getProperty("path");
		logLevel = Integer.parseInt(p.getProperty("logLevel", "0"));
		sequence = p.getProperty("sequence");
		dataBaseType = Integer.parseInt(p.getProperty("dataBaseType", "0"));
		entityNameStr = p.getProperty("Entityname");
		tableListStr = p.getProperty("TableName");
		dbDriver = p.getProperty("dbDriver");
		daoPackagePath = p.getProperty("daoPackagePath");
		overWrite = p.getProperty("overWrite");
		servicePackagePath = p.getProperty("servicePackagePath");
		modelPackagePath = p.getProperty("modelPackagePath");
		controllerPackagePath = p.getProperty("controllerPackagePath");
		serviceConstsPackagePath = p.getProperty("serviceConstsPackagePath");
		xmlConfigPath = p.getProperty("xmlConfigPath");
		jspPath = p.getProperty("jspPath");
		actionPrex = p.getProperty("actionPrex");

	}

	public void setConfigToProperties(Properties p) {
		p.setProperty("author", author);
		p.setProperty("version", version);
		p.setProperty("dbType", dbType);
		p.setProperty("dbSchema", dbSchema);
		p.setProperty("dbUsername", dbUsername);
		p.setProperty("dbPasswd", dbPasswd);
		p.setProperty("dbConnectString", dbConnectString);
		p.setProperty("packagePath", packagePath);
		p.setProperty("path", path);
		p.setProperty("logLevel", String.valueOf(logLevel));
		p.setProperty("sequence", sequence);
		p.setProperty("dataBaseType", String.valueOf(dataBaseType));
		p.setProperty("Entityname", entityNameStr);
		p.setProperty("TableName", tableListStr);
		p.setProperty("dbDriver", dbDriver);
		p.setProperty("daoPackagePath", daoPackagePath);
		p.setProperty("overWrite", overWrite);
		p.setProperty("servicePackagePath", servicePackagePath);
		p.setProperty("modelPackagePath", modelPackagePath);
		p.setProperty("controllerPackagePath", controllerPackagePath);
		p.setProperty("serviceConstsPackagePath", serviceConstsPackagePath);
		p.setProperty("xmlConfigPath", xmlConfigPath);
		p.setProperty("jspPath", jspPath);
		p.setProperty("actionPrex", actionPrex);

	}

	public Map<String, Object> getContextMap(String tableName) {
		String entityName = (String) getEntityName().get(tableName);
		Map<String, Object> entityMap = contextMap.get(entityName);
		if (entityMap == null) {
			entityMap = new HashMap<String, Object>();
			String daoClass = entityName + "Dao";
			String serviceClass = entityName + "Service";
			String controllerClass = entityName + "Controller";
			entityMap.put("tableName", tableName);
			entityMap.put("author", getAuthor());
			entityMap.put("version", getVersion());
			// path
			entityMap.put("packagePath", getPackagePath());
			entityMap.put("daoPackagePath", getDaoPackagePath());
			entityMap.put("servicePackagePath", getServicePackagePath());
			entityMap.put("modelPackagePath", getModelPackagePath());
			entityMap.put("controllerPackagePath", getControllerPackagePath());

			// class & instance
			entityMap.put("entityClass", entityName);
			entityMap.put("entityClassInstance", StringConverter.setFirstCharLowercase(entityName));

			entityMap.put("daoClass", daoClass);
			entityMap.put("daoClassInstance", StringConverter.setFirstCharLowercase(daoClass));

			entityMap.put("serviceClass", serviceClass);
			entityMap.put("serviceClassInstance", StringConverter.setFirstCharLowercase(serviceClass));

			entityMap.put("controllerClass", controllerClass);
			entityMap.put("controllerClassInstance", StringConverter.setFirstCharLowercase(controllerClass));

			entityMap.put("actionPrex", getActionPrex());

			entityMap.put("dateTime", TimerUtil.getStrDate());

			initEntityId(entityMap, tableName);
			contextMap.put(entityName, entityMap);
		}

		return entityMap;

	}

	private void initEntityId(Map<String, Object> entityMap, String tableName) {
		List<Column> columnList = DbSchemaProvider.getTableColumnNames(tableName);

		String getId = "getId";
		String entityId = "id";
		String IdType = "Long";

		for (Column column : columnList) {
			if (column != null && column.isPrimaryKeyColumn()) {
				getId = "get" + StringConverter.setFirstCharUpcase(column.getJavaName());
				entityId = column.getJavaName();
				IdType = column.getJavaSimpleType();
				break;
			}
		}

		entityMap.put("getId", getId);
		entityMap.put("entityId", entityId);
		entityMap.put("IdType", IdType);
	}

	public Map<String,String> getEntityName() {
		return entityName;
	}

	public Object getEntityName(String key) {
		return entityName.get(key);
	}

	public void setEntityName(Map<String,String> entityName) {
		this.entityName = entityName;
	}

	public String getDbDriver() {
		return dbDriver;
	}

	public void setDbDriver(String dbDriver) {
		this.dbDriver = dbDriver;
	}

	public String getDaoPackagePath() {
		return daoPackagePath;
	}

	public void setDaoPackagePath(String daoPackagePath) {
		this.daoPackagePath = daoPackagePath;
	}

	public String getOverWrite() {
		return overWrite;
	}

	public void setOverWrite(String overWrite) {
		this.overWrite = overWrite;
	}

	public String getServicePackagePath() {
		return servicePackagePath;
	}

	public void setServicePackagePath(String servicePackagePath) {
		this.servicePackagePath = servicePackagePath;
	}

	public String getModelPackagePath() {
		return modelPackagePath;
	}

	public void setModelPackagePath(String modelPackagePath) {
		this.modelPackagePath = modelPackagePath;
	}

	public String getControllerPackagePath() {
		return controllerPackagePath;
	}

	public void setControllerPackagePath(String controllerPackagePath) {
		this.controllerPackagePath = controllerPackagePath;
	}

	public String getServiceConstsPackagePath() {
		return serviceConstsPackagePath;
	}

	public void setServiceConstsPackagePath(String serviceConstsPackagePath) {
		this.serviceConstsPackagePath = serviceConstsPackagePath;
	}

	public String getXmlConfigPath() {
		return xmlConfigPath;
	}

	public void setXmlConfigPath(String xmlConfigPath) {
		this.xmlConfigPath = xmlConfigPath;
	}

	public String getJspPath() {
		return jspPath;
	}

	public void setJspPath(String jspPath) {
		this.jspPath = jspPath;
	}

	public String getActionPrex() {
		return actionPrex;
	}

	public void setActionPrex(String actionPrex) {
		this.actionPrex = actionPrex;
	}
}